package com.ctsh.centersh.guideview2

import android.app.Activity
import android.content.Context
import android.graphics.*
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.RelativeLayout
import com.ctsh.centersh.commonlib.DeviceUtil

/**
 * 蒙层引导.
 * created by cqy  on 2019/2/13 15:04.
 */
class GuideMaskView(context: Context?) : RelativeLayout(context), ViewTreeObserver.OnGlobalLayoutListener {
    private val TAG = javaClass.simpleName
    private var first = true

    companion object {
        private val SHOW_GUIDE_PREFIX = "show_guide_on_view_"
    }

    private var offsetX = 0 //GuideView 偏移量
    private var offsetY = 0
    private var radius: Int = 0 // targetView 的外切圆半径
    private var targetView: View? = null //需要显示提示信息的View
    private var onTargetView: View? = null //显示提示信息的Views上的蒙层View
    private var customGuideView: View? = null //自定义View
    private var mCirclePaint: Paint? = null //透明圆形画笔
    private var mBackgroundPaint: Paint? = null  //背景色画笔
    private var isMeasured: Boolean = false//targetView是否已测量
    private var center: IntArray? = null //targetView圆心
    private var porterDuffXfermode: PorterDuffXfermode? = null //绘图层叠模式
    private var bitmap: Bitmap? = null //绘制前景bitmap
    private var backgroundColors = 0 //背景色和透明度，格式 #aarrggbb
    private var temp: Canvas? = null// Canvas,绘制bitmap
    private var direction: Direction? = null //相对于targetView的位置.在target的那个方向
    private var myShape: MyShape? = null //形状
    private var location: IntArray? = null //targetView左上角坐标
    private var widthHeight: IntArray? = null //高亮区域的宽高 不设置默认为目标View的宽高
    private var guideWidthHeight: IntArray? = null //提示View的宽高 不设置默认为提示View的宽高
    private var onClickExit: Boolean = false
    private var onclickListener: OnClickCallback? = null
    private var onTargetClickListener: OnClickListener? = null
    private var onHideListener: OnHideListener? = null
    internal var needDraw = true
    fun restoreState() {
        offsetY = 0
        offsetX = offsetY
        radius = 0
        mCirclePaint = null
        mBackgroundPaint = null
        isMeasured = false
        center = null
        porterDuffXfermode = null
        bitmap = null
        needDraw = true
        temp = null
    }

    init {
        setClickInfo(this)
    }

    fun getRadius(): Int {
        return radius
    }

    fun getLocation(): IntArray? {
        return location
    }

    fun setLocation(location: IntArray) {
        this.location = location
    }

    fun setWidthHeight(x: Int, y: Int) {
        this.widthHeight = intArrayOf(x, y)
    }

    /**
     * 设置GuideView宽高.
     * @param x 宽px.
     * @param y 高px.
     */
    fun setgGuideWidthHeight(x: Int, y: Int) {
        this.guideWidthHeight = intArrayOf(x, y)
    }

    /**
     * 设置GuideView宽高.
     * @param x 宽dp.
     * @param y 高dp.
     */
    fun setgGuideWidthHeight(x: Float, y: Float): GuideMaskView {
        setgGuideWidthHeight(DeviceUtil.dp2px(context, x), DeviceUtil.dp2px(context, y))
        return this
    }

    /**
     *监听浮层消失.
     */
    fun setOnHideListener(l: OnHideListener) {
        this.onHideListener = l
    }

    /**
     * 设置圆角.
     */
    fun setRadius(radius: Int): GuideMaskView {
        this.radius = radius
        return this
    }

    fun setOffset(x: Float, y: Float): GuideMaskView {
        setOffsetX(x)
        setOffsetY(y)
        return this
    }

    fun setOffsetX(offsetX: Float) {
        this.offsetX = DeviceUtil.dp2px(context, offsetX)
    }

    fun setOffsetY(offsetY: Float) {
        this.offsetY = DeviceUtil.dp2px(context, offsetY)
    }

    fun setDirection(direction: Direction): GuideMaskView {
        this.direction = direction
        return this
    }

    fun setShape(shape: MyShape): GuideMaskView {
        this.myShape = shape
        return this
    }

    fun setCustomGuideView(customGuideView: View) {
        this.customGuideView = customGuideView
        if (!first) {
            restoreState()
        }
    }

    fun setCustomGuideView(customGuideViewID: Int): GuideMaskView {
        val iv = ImageView(context)
        iv.setImageResource(customGuideViewID)
        val params = LayoutParams(DeviceUtil.dp2px(context, 226F), DeviceUtil.dp2px(context, 35F))
        iv.layoutParams = params
        setCustomGuideView(iv)
        return this
    }

    fun setBgColor(backgroundColor: Int): GuideMaskView {
        backgroundColors = backgroundColor
        return this
    }

    fun getTargetView(): View? {
        return targetView
    }

    fun setTargetView(targetView: View): GuideMaskView {
        this.targetView = targetView
        return this
    }

    fun showOnce() {
        targetView?.let {
            context?.getSharedPreferences(TAG, Context.MODE_PRIVATE)?.edit()?.putBoolean(generateUniqId(it), true)
                ?.commit()
        }
    }

    fun getCenter(): IntArray? {
        return center
    }

    fun setCenter(center: IntArray) {
        this.center = center
    }

    fun hide() {
        customGuideView?.let {
            onHideListener?.onHide(it)
            targetView?.viewTreeObserver?.removeOnGlobalLayoutListener(this)
            this.removeAllViews()
            ((context as Activity).window.decorView as FrameLayout).removeView(this)
            restoreState()
        }
    }

    private fun hasShown(): Boolean {
        targetView?.let { targetView ->
            context?.let { context ->
                return context.getSharedPreferences(TAG, Context.MODE_PRIVATE)
                    .getBoolean(generateUniqId(targetView), false)
            }
        }
        return true
    }

    fun show(): GuideMaskView {
        if (hasShown())
            return this
        targetView?.let {
            it.viewTreeObserver.addOnGlobalLayoutListener(this)
        }
        this.setBackgroundResource(R.color.transparent)
        ((context as Activity).window.decorView as FrameLayout).addView(this)
        first = false
        return this
    }

    /**
     * 添加提示文字，位置在targetView的下边
     * 在屏幕窗口，添加蒙层，蒙层绘制总背景和透明圆形，圆形下边绘制说明文字
     */
    private fun createGuideView() {
        // Tips布局参数
        var guideViewParams: LayoutParams
        guideViewParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        //引导view宽高测量.
        var w = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
        var h = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
        customGuideView?.measure(w, h)
        var guideViewSize = intArrayOf(
            customGuideView?.measuredWidth
                ?: 0, customGuideView?.measuredHeight ?: 0
        )
        guideWidthHeight?.let {
            guideViewParams = LayoutParams(it[0], it[1])
            guideViewSize = intArrayOf(it[0], it[1])
        }
        customGuideView?.let { customGuideView ->
            if (direction != null) {
                center?.let { center ->
                    var mLeft = center[0]
                    var mTop = center[1]
                    when (direction) {
                        Direction.TOP -> {
                            guideViewParams.setMargins(
                                mLeft,
                                mTop - getTargetViewSize()[1] / 2 - guideViewSize[1],
                                0,
                                0
                            )
                        }
                        Direction.LEFT -> {
                            guideViewParams.setMargins(
                                mLeft - getTargetViewSize()[0] / 2 - guideViewSize[0],
                                mTop - getTargetViewSize()[1] / 2,
                                0,
                                0
                            )
                        }
                        Direction.BOTTOM -> {
                            guideViewParams.setMargins(
                                mLeft - guideViewSize[0] / 2 + offsetX,
                                mTop + getTargetViewSize()[1] / 2 + offsetY,
                                0,
                                0
                            )
                        }
                        Direction.RIGHT ->
                            guideViewParams.setMargins(
                                mLeft + getTargetViewSize()[0] / 2,
                                mTop - getTargetViewSize()[1] / 2,
                                0,
                                0
                            )
                        Direction.LEFT_TOP -> {
                            guideViewParams.setMargins(
                                mLeft,
                                mTop - getTargetViewSize()[1] / 2 - getTargetViewSize()[1],
                                0,
                                0
                            )
                        }
                        Direction.LEFT_BOTTOM -> {
                            guideViewParams.setMargins(mLeft, mTop + getTargetViewSize()[1] / 2, 0, 0)
                        }
                        Direction.RIGHT_TOP -> {
                            guideViewParams.setMargins(
                                mLeft - guideViewSize[0],
                                mTop - getTargetViewSize()[1] / 2 - guideViewSize[1],
                                0,
                                0
                            )
                        }
                        Direction.RIGHT_BOTTOM -> {
                            guideViewParams.setMargins(
                                mLeft - guideViewSize[0] + offsetX,
                                mTop + getTargetViewSize()[1] / 2 + offsetY,
                                0,
                                0
                            )
                        }
                    }
                }
            } else {
                guideViewParams = LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                guideViewParams.setMargins(offsetX, offsetY, 0, 0)
            }
            if (customGuideView.parent == null) {
                this.addView(customGuideView, guideViewParams)
            }
        }
    }

    /**
     * 获得targetView 的宽高，如果未测量，返回｛-1， -1｝.
     * @return
     */
    private fun getTargetViewSize(): IntArray {
        val location = intArrayOf(-1, -1)
        if (isMeasured) {
            targetView?.let {
                location[0] = it.width
                location[1] = it.height
            }
        }
        return location
    }

    /**
     * 获得targetView 的半径
     * @return
     */
    private fun getTargetViewRadius(): Int {
        if (isMeasured) {
            val size = getTargetViewSize()
            val x = size[0]
            val y = size[1]
            return (Math.sqrt((x * x + y * y).toDouble()) / 2).toInt()
        }
        return -1
    }

    private fun drawBackground(canvas: Canvas) {
        needDraw = false
        // 先绘制bitmap，再将bitmap绘制到屏幕
        bitmap = Bitmap.createBitmap(canvas.width, canvas.height, Bitmap.Config.ARGB_8888)
        temp = Canvas(bitmap)

        // 背景画笔
        val bgPaint = Paint()
        if (backgroundColors != 0)
            bgPaint.color = backgroundColors
        else
            bgPaint.color = resources.getColor(R.color.color_b3000000)

        // 绘制屏幕背景
        temp?.let {
            it.drawRect(0f, 0f, it.width.toFloat(), it.height.toFloat(), bgPaint)
        }
        // targetView 的透明圆形画笔
        if (mCirclePaint == null)
            mCirclePaint = Paint()
        porterDuffXfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)// 或者CLEAR
        mCirclePaint?.let {
            it.xfermode = porterDuffXfermode
            it.isAntiAlias = true
            it.color = resources.getColor(R.color.transparent)
        }

        if (myShape != null) {
            val oval = RectF()
            var height = targetView?.measuredHeight?.div(2)
            var width = targetView?.measuredWidth?.div(2)
            widthHeight?.let {
                height = it[1]
                width = it[0]
            }
            when (myShape) {
                //圆
                MyShape.CIRCULAR -> center?.let {
                    temp?.drawCircle(it[0].toFloat(), it[1].toFloat(), radius.toFloat(), mCirclePaint)//绘制圆形
                }
                MyShape.ELLIPSE//椭圆
                -> {
                    center?.let {
                        //RectF对象
                        width?.let { width ->
                            height?.let { height ->
                                oval.left = (it[0] - width).toFloat()//左边
                                oval.top = (it[1] - height).toFloat() //上边
                                oval.right = (it[0] + width).toFloat() //右边
                                oval.bottom = (it[1] + height).toFloat() //下边
                            }
                        }
                        temp?.drawOval(oval, mCirclePaint)
                    }//绘制椭圆
                }
                MyShape.RECTANGULAR//圆角矩形
                -> {
                    //RectF对象
                    center?.let {
                        width?.let { width ->
                            height?.let { height ->
                                oval.left = (it[0] - width).toFloat()//左边
                                oval.top = (it[1] - height).toFloat()//上边
                                oval.right = (it[0] + width).toFloat()//右边
                                oval.bottom = (it[1] + height).toFloat()//下边
                            }
                        }
                        temp?.drawRoundRect(oval, radius.toFloat(), radius.toFloat(), mCirclePaint)//绘制圆角矩形
                    }
                }
            }
        } else {
            center?.let {
                temp?.drawCircle(it[0].toFloat(), it[1].toFloat(), radius.toFloat(), mCirclePaint)//绘制圆形
            }
        }

        // 绘制到屏幕
        canvas.drawBitmap(bitmap, 0f, 0f, bgPaint)
        bitmap?.recycle()
    }

    fun setOnClickExit(onClickExit: Boolean) {
        this.onClickExit = onClickExit
    }

    fun setOnclickListener(onclickListener: OnClickCallback): GuideMaskView {
        this.onclickListener = onclickListener
        return this
    }

    fun setTargetclickListener(onclickListener: OnClickListener): GuideMaskView {
        this.onTargetClickListener = onclickListener
        return this
    }

    private fun generateUniqId(v: View): String {
        return SHOW_GUIDE_PREFIX + v.id
    }

    private fun setClickInfo(v: View) {
        val exit = onClickExit
        setOnClickListener {
            onclickListener?.let {
                it.onClickedGuideView(v)
            }
            if (exit) {
                hide()
            }
        }
    }

    override fun onGlobalLayout() {
        if (isMeasured)
            return
        targetView?.let {
            if (it.height > 0 && it.width > 0) {
                isMeasured = true
            }
            // 获取targetView的中心坐标
            if (center == null) {
                // 获取右上角坐标
                location = IntArray(2)
                it.getLocationInWindow(location)
                center = IntArray(2)
                // 获取中心坐标
                center?.let { center ->
                    location?.let { location ->
                        center[0] = location[0] + it.width / 2
                        center[1] = location[1] + it.height / 2
                    }
                }
            }
        }
        // 获取targetView外切圆半径
        if (radius == 0) {
            radius = getTargetViewRadius()
        }
        createGuideView()// 添加GuideView
        createOnTargetView()
    }

    /**
     * 添加targetView蒙层
     * 蒙层绘制总背景上绘制targetView蒙层
     */
    private fun createOnTargetView() {
        // Tips布局参数
        targetView?.let { targetView ->
            onTargetView = RelativeLayout(context)
            var mHeight = targetView.measuredHeight
            var mWidth = targetView.measuredWidth
            var onTargetViewParams = LayoutParams(mWidth, mHeight)
            center?.let {
                var mLeft = it[0] - mWidth.div(2)
                var mTop = it[1] - mHeight.div(2)
                onTargetViewParams.setMargins(mLeft, mTop, 0, 0)
            }
            if (onTargetView?.parent == null) {
                this.addView(onTargetView, onTargetViewParams)
            }
            onTargetClickListener?.let {
                onTargetView?.setOnClickListener(it)
            }
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (!isMeasured)
            return
        if (targetView == null)
            return
        drawBackground(canvas)
    }

    /**
     * 定义GuideView相对于targetView的方位，共八种。不设置则默认在targetView下方
     */
    enum class Direction {
        LEFT, TOP, RIGHT, BOTTOM,
        LEFT_TOP, LEFT_BOTTOM,
        RIGHT_TOP, RIGHT_BOTTOM
    }

    /**
     * 定义目标控件的形状，共3种。圆形，椭圆，带圆角的矩形（可以设置圆角大小），不设置则默认是圆形
     */
    enum class MyShape {
        CIRCULAR, ELLIPSE, RECTANGULAR
    }

    /**
     * GuideView点击Callback
     */
    interface OnClickCallback {
        fun onClickedGuideView(v: View)
    }

    interface OnHideListener {
        /**
         * This method will be invoked when the  is hide.
         * @param dialog the dialog that was dismissed will be passed into the
         * method
         */
        fun onHide(v: View)
    }

}